#!/usr/bin/python
# -*- coding: utf-8 -*-

u"""
"""

__version__ = '$Id$'


import sys
import os

import unittest
import warnings

# find the local copy
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))

from bipy import events


class TestEvent(unittest.TestCase):

    def add_handler(self, *args, **kwargs):
        self.event += self.handler
        self.event += self.handler2
        self.call_order.append('add_handler')

    def self_remove(self, *args, **kwargs):
        self.event -= self.self_remove
        self.call_order.append('self_remove')

    def handler(self, *args, **kwargs):
        self.handler_data.append((args, kwargs))
        self.call_order.append('handler')

    def handler2(self, *args, **kwargs):
        self.handler2_data.append((args, kwargs))
        self.call_order.append('handler2')

    def handled(self, *args, **kwargs):
        self.handler_data.append((args, kwargs))
        self.call_order.append('handled')
        return events.Event.HANDLED

    def handle_source(self, *args, **kwargs):
        self.handler_data.append((args, kwargs))
        source, data = args
        source -= self.handle_source
        self.call_order.append('handle_source')

    def setUp(self):
        self.event = events.Event()
        self.handler_data = []
        self.handler2_data = []
        self.call_order = []

    def test_00_add(self):
        self.event += self.handler
        self.event('1')
        self.assertEquals(self.handler_data, [(('1',), {})])

    def test_01_remove(self):
        self.event += self.handler
        self.event('1')
        self.event -= self.handler
        self.assertEquals(self.handler_data, [(('1',), {})])

    def test_02_add_remove(self):
        self.event += self.handler
        self.event -= self.handler
        self.event('3')
        self.assertEquals(self.handler_data, [])

    def test_03_add_remove2(self):
        self.event += self.handler
        self.event += self.handler2
        self.event -= self.handler
        self.event('4')
        self.assertEquals(self.handler2_data, [(('4',), {})])
        self.assertEquals(self.handler_data, [])

    def test_04_len(self):
        warnings.simplefilter('error')
        try:
            self.assertEquals(len(self.event), 0)
            self.event += self.handler
            len(self.event)
            self.assertEquals(len(self.event), 1)
            self.event -= self.handler
            self.assertEquals(len(self.event), 0)
            #print len(self.event._to_add), len(self.event._to_remove), len(self.event._callbacks), '\n'
            self.event += self.handler
            self.event += self.handler2
            self.assertEquals(len(self.event), 2)
            self.event -= self.handler
            self.assertEquals(len(self.event), 1)
        except event.AddTwiceWarning:
            self.fail('Warning was raised')
        finally:
            warnings.resetwarnings()

    def test_05_fire(self):
        self.event += self.handler
        self.event += self.handler2
        self.event('8', name='bla')
        self.assertEquals(self.handler_data, [(('8',), {'name':'bla'})])
        self.assertEquals(self.handler2_data, [(('8',), {'name':'bla'})])

    def test_06_self_remove(self):
        self.event += self.self_remove
        self.assertEquals(len(self.event), 1)
        self.event()
        self.assertEquals(len(self.event), 0)

    def test_06a_self_remove(self):
        self.event += self.handle_source
        self.assertEquals(len(self.event), 1)
        self.event(self.event, '6a', name='bla')
        self.assertEquals(len(self.event), 0)
        self.assertEquals(self.handler_data, [((self.event, '6a',), {'name':'bla'})])

    def test_07_adder(self):
        self.event += self.add_handler
        self.assertEquals(len(self.event), 1)
        self.event()
        self.assertEquals(len(self.event), 3)

    def test_08_warnings(self):
        try:
            warnings.simplefilter('error')
            self.event += self.handler
            self.assertRaises(events.AddTwiceWarning, self.event.add, self.handler)
            self.event -= self.handler
            self.assertRaises(events.RemoveWarning, self.event.remove, self.handler)
        finally:
            warnings.resetwarnings()

    def test_09_remove_non_existent(self):
        try:
            warnings.simplefilter("ignore")
            self.event -= self.handler
            self.event()
        except:
            self.fail('removing unkown handler should not raise any exception')
        finally:
            warnings.resetwarnings()

    def test_10_return_HANDELD_order(self):
        self.event += self.handled
        self.event += self.handler2
        self.event()
        #print '\n', self.call_order
        self.failUnless(self.call_order==['handler2', 'handled'], 'wrong callorder')
        self.failUnless(len(self.handler_data)==1, 'no influence, wrong order')
        self.failUnless(len(self.handler2_data)==1, 'no influence, wrong order 2')

    def test_11_return_HANDELD(self):
        self.event += self.handler2
        self.event += self.handled
        self.event()
        #print '\n', self.call_order
        self.failUnless(self.call_order==['handled'], 'wrong callorder')
        self.failUnless(len(self.handler_data)==1, 'order, break processing')
        self.failUnless(len(self.handler2_data)==0, 'order, break processing 2')

    def test_12_clear(self):
        self.event += self.handler
        self.event += self.handler2
        self.event += self.handled
        self.assertEquals(len(self.event), 3)
        self.event.clear()
        self.assertEquals(len(self.event), 0)

class TestReversedEvent(TestEvent):

    def setUp(self):
        self.event = events.ReversedEvent()
        self.handler_data = []
        self.handler2_data = []
        self.call_order = []

    def test_10_return_HANDELD_order(self):
        self.event += self.handled
        self.event += self.handler2
        self.event()
        #print '\n', self.call_order
        self.failUnless(self.call_order==['handled'], 'wrong callorder')
        self.failUnless(len(self.handler_data)==1, 'no influence, wrong order')
        self.failUnless(len(self.handler2_data)==0, 'no influence, wrong order 2')

    def test_11_return_HANDELD(self):
        self.event += self.handler2
        self.event += self.handled
        self.event()
        #print '\n', self.call_order
        self.failUnless(self.call_order==['handler2', 'handled'], 'wrong callorder')
        self.failUnless(len(self.handler_data)==1, 'order, break processing')
        self.failUnless(len(self.handler2_data)==1, 'order, break processing 2')


if __name__ == '__main__':
    unittest.main()
